/**
 * Copyright (c) 2003-2021 The Apereo Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *             http://opensource.org/licenses/ecl2
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sakaiproject.entitybroker.providers;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import lombok.extern.slf4j.Slf4j;

import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.event.api.Event;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserDirectoryService;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.util.EmailNotification;
import org.sakaiproject.util.ResourceLoader;

/**
 * ExternalEmailNotification handles events generated by {@link NotificationEntityProvider}. It generates the emails
 * requested by the external system.
 *
 * Added for https://jira.sakaiproject.org/browse/SAK-25733
 * @author Bill Smith (wsmith @ unicon.net)
 * @author Aaron Zeckoski (azeckoski @ gmail.com) (azeckoski @ unicon.net)
 */
@Slf4j
public class ExternalEmailNotification extends EmailNotification {
    private static final String EMAIL_SUBJECT_PROP = "notify_post_subject";

    private ThreadLocal<String> message = new ThreadLocal<String>();

    private UserDirectoryService userDirectoryService;

    /**
     * Default constructor
     */
    public ExternalEmailNotification() {
        this.userDirectoryService = (UserDirectoryService) ComponentManager.get(UserDirectoryService.class);
    }

    /**
     * To be called when a new event is being created. Allows the event to set the emailBody content for the
     * notification.
     *
     * @param emailBody
     *         the email body to be added
     */
    public void addMessage(String emailBody) {
        if (log.isDebugEnabled()) {
            log.debug("Adding new request!\nemailBody: " + emailBody);
        }
        message.set(emailBody);
    }

    /* (non-Javadoc)
     * @see org.sakaiproject.util.EmailNotification#getHeaders(org.sakaiproject.event.api.Event)
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected List getHeaders(Event event) {
        List<String> rv = super.getHeaders(event);

        // set the subject
        try {
            User user = this.userDirectoryService.getUser(event.getContext());
            // get subject from resource bundle based on user's locale
            ResourceBundle bundle = ResourceBundle.getBundle("notify", getUserLocale(user.getId()));
            rv.add("Subject: " + bundle.getString(EMAIL_SUBJECT_PROP));
        } catch (UserNotDefinedException e) {
            throw new IllegalStateException(e);
        }

        // to
        rv.add(getTo(event));

        return rv;
    }

    /**
     * @param userId Sakai user id
     * @return correct Locale for the user based on prefs
     */
    private Locale getUserLocale(String userId) {
        Locale locale = new ResourceLoader().getLocale(userId);
        if (locale == null) {
            // since this can be a null if it is not set we will force it to make sure it is good
            locale = new ResourceLoader().getLocale();
            if (locale == null) {
                locale = Locale.getDefault();
            }
        }
        return locale;
    }

    /* (non-Javadoc)
     * @see org.sakaiproject.util.EmailNotification#getMessage(org.sakaiproject.event.api.Event)
     */
    @Override
    protected String getMessage(Event event) {
        StringBuilder message = new StringBuilder();
        message.append(MIME_ADVISORY);

        message.append(BOUNDARY_LINE);
        message.append(plainTextHeaders());
        message.append(plainTextContent(event));

        message.append(TERMINATION_LINE);
        return message.toString();
    }

    /* (non-Javadoc)
     * @see org.sakaiproject.util.EmailNotification#getRecipients(org.sakaiproject.event.api.Event)
     */
    @Override
    protected List<User> getRecipients(Event event) {
        ArrayList<User> recipients = new ArrayList<User>();
        String userId = event.getContext();
        try {
            User user = this.userDirectoryService.getUser(userId);
            recipients.add(user);
        } catch (UserNotDefinedException e) {
            throw new IllegalStateException(e);
        }
        return recipients;
    }

    /**
     * Generate the To header based on the event data
     * @param event
     * @return
     */
    private String getTo(Event event) {
        String to = null;
        try {
            User user = this.userDirectoryService.getUser(event.getContext());
            to = "To: " + user.getEmail();
        } catch (UserNotDefinedException e) {
            throw new IllegalStateException(e);
        }
        return to;
    }

    /* (non-Javadoc)
     * @see org.sakaiproject.util.EmailNotification#plainTextContent(org.sakaiproject.event.api.Event)
     */
    @Override
    protected String plainTextContent(Event event) {
        StringBuilder buf = new StringBuilder();
        buf.append(message.get());
        return buf.toString();
    }

    /* (non-Javadoc)
     * @see org.sakaiproject.util.EmailNotification#getType
     */
    protected String getType(String resourceFilter) {
        return "sakai:external";
    }

}
